
// Pixybit 0.1 - the 8-bit Ardiuno Uno + Gameduino runtime

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <SPI.h>
#include <EEPROM.h>
#include <GD.h>
#include <font8x8.h>

// C includes
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include "runtime.h" // the PIXYBIT OS Runtime
#include "user.h" // the user-space sw modules ( up to 5 )

//extern char* __brkval;
//extern char __heap_start;

// attach user-space software here
// please note that we have up-to 5 module slots available
// and that the framework will only init-and-run modules
// that have properly registered callbacks for both setup() and loop() !!
void attach_user_space_sw(void)
{
  // attach setup functions
  attach_user_Setup1(setup_user_1);
  // ...
  // add additional user space software setup methods as needed
  
  // attach loop functions
  attach_user_Loop1(loop_user_1);
  // ...
  // add additional user space software loop methods as needed
}

void minimize_power_consumption()
{
    DDRD &= B00000011;       // set Arduino pins 2 to 7 as inputs, leaves 0 & 1 (RX & TX) as is
    DDRB = B00000000;        // set pins 8 to 13 as inputs
    PORTD |= B11111100;      // enable pullups on pins 2 to 7, leave pins 0 and 1 alone(RX & TX)
    PORTB |= B11111111;      // enable pullups on pins 8 to 13
    
    pinMode(PIXIE_TILT_SENSOR, INPUT); // tilt sensor will be on PIN 2 / Interrupt0
    digitalWrite(PIXIE_TILT_SENSOR, HIGH);   // turn on the built in pull-up resistor
    
    pinMode(PIXIE_ATTENTION_LED, OUTPUT);      // set pin 8 as an output so we can use LED to monitor
    digitalWrite(PIXIE_ATTENTION_LED, LOW);    // turn the LED 8 off
}

void setup()
{
  
  minimize_power_consumption();
  
  // this methods attaches up to 5 user space modules
  attach_user_space_sw(); 
   
  ERR = pixie_setup();

  if (ERR) pixie_shutdown();
  else
  pixie_ready(); 

  // set up user space SW
  // setup_user_1();
  
  // call "setup" on up-to 5 user space modules
  // please note that these routines are CALLBACKS, so 
  // the framework only calls those that *are registered* !!
  setup_user_space_software(); 

  byte eeprom_valid = 0;
  
  eeprom_valid = EEPROM.read(0);
 
  // check for valid configuration stored in EEPROM 
  if (27 == eeprom_valid)
  {
    
    // retreive environmnet variables 
    VSYNC           = EEPROM.read(EEPROM_LAST_MSG + 1);
    CLRSCR          = EEPROM.read(EEPROM_LAST_MSG + 2);
    SHADER_PROGRAMS = EEPROM.read(EEPROM_LAST_MSG + 3);
    // .. other environment variables can be added here as necessary
    
    // retrieve last valid command 
    READ_SERIAL = EEPROM.read(EEPROM_LAST_MSG);

    Serial.println(F("Resuming Execution of command: "));
    Serial.println(READ_SERIAL);

  } 
  
  
  //
  // *********** start execution of command retrieved from EEPROM !!
  //
  loop_interpret_comm();
  //
  //
  //
}

void loop()
{
  
  // handle the timers, we have 6 of them
  loop_check_timers();
  
  // checks for button press of PIXIE_BUTTON_A (Digital Pin 4) and PIXIE_BUTTON_B ( Digital Pin 7)
  loop_check_buttons();
  
  // checks tilt sensor, sets PIXIE_SENSOR_TILTED so that user sw can use this flag to detect a TILT of the DEVICE.
  loop_check_sensors();

  // listen for commands from the PC
  loop_listen_comm();
  
  // act on these commands as necessary
  if (SERIAL_COMM)       
  {
    loop_interpret_comm();
    SERIAL_COMM = false;
  }

  // back up last command in case command #99 is issued 
  // to save environment info to EEPROM
  SAVE_SERIAL = READ_SERIAL;
  
  // the main arduino exec. loop
  if (ARDUINO_COMMAND)   
  {
    loop_arduino();
  }
  
  // the main gameduino exec. loop
  if (GAMEDUINO_COMMAND)
  {
    loop_gameduino();
  }
  
  // the entry for Async. communication with the PC
  if (SOMETHING_TO_SAY)  
  {
    loop_speak_comm();
    SOMETHING_TO_SAY = false;
  }
 
  // error handling 
  if (ERR || FAIL)       check_for_error();

  // once the Timer Interrupt occurs, this is set TRUE by the ISR,  
  // then this "one-time event" is handled (if necessary) inside the main loop()
  // by checking this variable.
  loop_reset_timers();
  
  loop_reset_buttons();

  loop_reset_sensors();  
  
}
